/*
 * FNIDateFormat - Java style date formatter
 * Copyright (C) 2008 - 2009 Antti Leppä / Foyt
 * http://www.foyt.fi
 * 
 * License: 
 * 
 * Licensed under GNU Lesser General Public License Version 2.1 or later (the "LGPL") 
 * http://www.gnu.org/licenses/lgpl.html
 */

fni.locale.dateformat.FNIDateFormat = Class.create(
  /** @lends fni.locale.dateformat.FNIDateFormat# */ 
  {
  /**
   * Constructor for FNIDateFormat class 
   * @class Class that handles localization
   * @param pattern format is specified by pattern of string. Following patterns may be used to format dates and times:
   * <table>
   *   <tr><td><b>Symbol</b></td><td><b>Component</b></td><td><b>Details</b></td></tr>
   *   <tr><td>y</td><td>year</td><td>yy = 09, yyyy = 2009</td></tr>
   *   <tr><td>M</td><td>month</td><td>M = 1, MM = 01, MMMM = localized month name</td></tr>
   *   <tr><td>d</td><td>day in month</td><td>d = 3, DD = 03</td></tr>
   *   <tr><td>E</td><td>day in week</td><td>E = localized day (short), EE = localized day (long)</td></tr> 
   *   <tr><td>a</td><td>a.m./p.m.</td><td></td></tr>
   *   <tr><td>k</td><td>Hour in day</td><td>k = 1, kk = 01</td></tr>
   *   <tr><td>h</td><td>Hour in day am/pm</td><td>h = 1, hh = 01</td></tr>
   *   <tr><td>m</td><td>Minute in hour</td><td>m = 1, mm = 01</td></tr>
   *   <tr><td>s</td><td>Second in minute</td><td>s = 1, ss = 01</td></tr>
   *   <tr><td>S</td><td>Millisecond</td><td>S = 5, SSS = 005</td></tr>
   * </table>
   * @constructs
   */
  initialize : function (pattern) {
    this._pattern = pattern;
    this._tokenFormatters = new Array();
    
    this._localizedMonth = false;
    this._localizedDayShort = false;
    this._localizedDayLong = false;
    
    var parsed = pattern;
    var formatters = fni.locale.dateformat.FNITokenFormatterVault.getFormatters();
    var keys = formatters.keys().sortBy(function(s) { return -s.length; });
    
    var cIndex = 0;
    
    while (cIndex < pattern.length) {
      var matched = false;
      
      if (pattern[cIndex] == '"') {
        cIndex++;
        while (pattern[cIndex] != '"') {
          this._tokenFormatters.push(pattern[cIndex]);
          cIndex++;
        }
        cIndex++;
      }
      
      for (var i = 0, len = keys.length; i < len; i++) {
        var formatter = formatters.get(keys[i]);
        var token = formatter.getToken();
        if (parsed.indexOf(token) == cIndex) {
          this._tokenFormatters.push(formatter);
          cIndex += token.length;
          matched = true;
          
          switch (token) {
            case 'E':
              this._localizedDayShort = true;
            break;
            case 'EE':
              this._localizedDayLong = true;
            break;
            case 'MMMM':
              this._localizedMonth = true;
            break;
          }  
          
          break;
        } 
      }
      
      if (!matched) {
        this._tokenFormatters.push(pattern[cIndex]);
        cIndex += 1;
      }
    }
  },
  /**
   * Formats date object into string
   * 
   * @param locale used locale
   * @param date date object
   * @returns formatted string
   */
  format: function (locale, date) {
    var result = '';
    
    for (var i = 0, len = this._tokenFormatters.length; i < len; i++) {
      var token = this._tokenFormatters[i];
      if (Object.isString(token))
        result += token;
      else
        result += token.format(date);
    }
    
    if (this._localizedDayLong) {
      var i = result.length;
      while ((i = result.lastIndexOf('__EL', i - 1)) >= 0) {
        var n = result.substring(i + 4, i + 6);
        result = result.substring(0, i) + locale.getText('weekdayLong_' + n) + result.substring(i + 6);
      } 
    }
    
    if (this._localizedDayShort) {
      var i = result.length;
      while ((i = result.lastIndexOf('__EE', i - 1)) >= 0) {
        var n = result.substring(i + 4, i + 6);
        result = result.substring(0, i) + locale.getText('weekdayShort_' + n) + result.substring(i + 6);
      } 
    }
    
    if (this._localizedMonth) {
      var i = result.length;
      while ((i = result.lastIndexOf('__MM', i - 1)) >= 0) {
        var n = result.substring(i + 4, i + 6);
        result = result.substring(0, i) + locale.getText('month_' + n) + result.substring(i + 6);
      } 
    }
    
    return result;
  },
  /**
   * Returns a pattern string describing this date format. 
   * 
   * @returns a pattern string describing this date format. 
   */
  getPattern: function () {
    return this._pattern;
  }
});